﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO.Ports;
using System.IO;
using System.Threading;

namespace PIM_ATE
{
    class MircoComHelper
    {
        private string m_sPortName = "";
        public byte m_sEnding = (byte)'$';
        public int m_iCountEnding = 1;
        public string PortName
        {
            set { m_sPortName = value; }
            get { return m_sPortName; }
        }

        private StringBuilder m_sbErr = new StringBuilder(256);
        public string ErrorMessage
        {
            get { return m_sbErr.ToString(); }
        }

        public MircoComHelper() { }
        List<Byte> m_lstBuffer = new List<byte>();
        bool m_bConnected = false;

        //private ManualResetEvent comRcvEvent = new ManualResetEvent(false);
        public delegate void ReadEventHandler(object sender, ReadEventArgs e);
        public event ReadEventHandler readEvent;
        private SerialPort m_portObj;

        public bool Close()
        {
            if (this.m_portObj.IsOpen)
            {
                this.m_portObj.Close();
            }
            return true;
        }

        public bool Connect(string Name, int baud = 9600, Parity pty = Parity.None, int bit = 8)
        {
            m_sPortName = Name;
            this.m_sbErr.Length = 0;
            try
            {
                this.m_portObj = new SerialPort(m_sPortName, baud, pty, bit, StopBits.One);
                //this.m_portObj.ReceivedBytesThreshold = 11;
                //this.m_portObj.DataReceived += new SerialDataReceivedEventHandler(cport_DataReceived);
                this.m_portObj.Open();
                m_bConnected = true;
                return true;
            }
            catch (Exception ex)
            {
                this.m_sbErr.Append(ex.Message);
                m_bConnected = false;
                return false;
            }
        }

        public void Dispose()
        {
            if (this.m_portObj != null && this.m_portObj.IsOpen)
            {
                this.m_portObj.Close();
                this.m_portObj.Dispose();
            }
        }

        //void cport_DataReceived(object sender, SerialDataReceivedEventArgs e)
        //{
        //    SerialPort sp = sender as SerialPort;
        //    Byte[] buf = new Byte[sp.BytesToRead];
        //    int length = sp.Read(buf, 0, buf.Length);

        //    if (ComReadAndUnpack(buf, length))
        //    {
        //        comRcvEvent.Set();
        //    }

        //    if (this.readEvent != null)
        //    {
        //        this.readEvent(this, null);
        //    }
        //}

        public bool StartWrite(Byte[] buf, bool isDirect = false, int timeout = 5000)
        {
            //int cnt = 0;
            m_lstBuffer.Clear();
            //comRcvEvent.Reset();

            //do
            //{
            //    this.cport.DiscardInBuffer();
            //    this.cport.Write(buf, 0, buf.Length);
            //    if (isDirect) return true;
            //} while (!comRcvEvent.WaitOne(timeout, true) && ++cnt < 3);

            //为了速度放弃重试次数

            this.m_portObj.DiscardInBuffer();
            this.m_portObj.Write(buf, 0, buf.Length);

            if (isDirect) return true;

            for (int i = 0; i < timeout / 50; i++)
            {
                if (m_portObj.BytesToRead > 0)
                {
                    Byte[] read_buf = new Byte[m_portObj.BytesToRead];
                    int length = m_portObj.Read(read_buf, 0, read_buf.Length);

                    if (ComReadAndUnpack(read_buf, length))
                    {
                        //comRcvEvent.Set();
                        return true;
                    }
                }
                Thread.Sleep(50);
            }

            return false;
            //return comRcvEvent.WaitOne(timeout, true);
        }

        public Byte[] StartRead()
        {
            return m_lstBuffer.ToArray();
        }

        public Byte[] StartRead(string ending, int timeout)
        {

            for (int i = 0; i < timeout / 50; i++)
            {
                if (m_portObj.BytesToRead > 0)
                {
                    Byte[] read_buf = new Byte[m_portObj.BytesToRead];
                    int length = m_portObj.Read(read_buf, 0, read_buf.Length);

                    ComReadAndUnpack(read_buf, length);
                    string ret = Encoding.ASCII.GetString(StartRead());

                    if (ret.Contains(ending))
                    {
                        return m_lstBuffer.ToArray();
                    }

                    //if (ComReadAndUnpack(read_buf, length))
                    //{
                    //    //comRcvEvent.Set();
                    //}
                }
                Thread.Sleep(50);
            }

            //if (comRcvEvent.WaitOne(timeout, true))
            //    return m_lstBuffer.ToArray();
            //else
            return null;
        }

        private bool ComReadAndUnpack(Byte[] buf, int length)
        {
            m_lstBuffer.AddRange(buf);
            int local = 0;
            int count = 0;
            while(true)
            {
                local = m_lstBuffer.IndexOf(m_sEnding, local + 1);
                if (local > 0)
                    count++;
                else
                    break;
            }

            return count == m_iCountEnding;
            //return m_lstBuffer.IndexOf(m_sEnding) > 0;
        }

    }

    class ReadEventArgs
    {
        public ReadEventArgs(string s) { Text = s; }
        public String Text {get; set;}       
    }
}
